(function($){
	$.fn.uploadFile = function(options){
		var defaults = {
				iBytesUploaded : 0,
				iBytesTotal : 0,
				iPreviousBytesLoaded : 0,
				iMaxFilesize : 1048576, // 1MB
				oTimer : 0,
				sResultFileSize : '',
				uploadBtnId:'#upload_btn',
				sendMethod:'POST',
				url:'upload.jsp',
				formId:'#upload_form',
				uploadResponse:'#upload_response',
				timeInterval:300
		};
		options = $.extend(defaults,options);
		
		var secondsToTime = function(secs) { // we will use this function to convert seconds in normal time format
		    var hr = Math.floor(secs / 3600);
		    var min = Math.floor((secs - (hr * 3600))/60);
		    var sec = Math.floor(secs - (hr * 3600) -  (min * 60));

		    if (hr < 10) {hr = "0" + hr; }
		    if (min < 10) {min = "0" + min;}
		    if (sec < 10) {sec = "0" + sec;}
		    if (hr) {hr = "00";}
		    return hr + ':' + min + ':' + sec;
		};
		var bytesToSize = function(bytes) {
		    var sizes = ['Bytes', 'KB', 'MB'];
		    if (bytes == 0) return 'n/a';
		    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
		    return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
		};
		var doInnerUpdates = function() { // we will use this function to display upload speed
			
		    var iCB = options.iBytesUploaded;
		    var iDiff = iCB - options.iPreviousBytesLoaded;

		    // if nothing new loaded - exit
		    if (iDiff == 0)
		        return;

		    options.iPreviousBytesLoaded = iCB;
		    iDiff = iDiff * 2;
		    var iBytesRem = options.iBytesTotal - options.iPreviousBytesLoaded;
		    var secondsRemaining = iBytesRem / iDiff;

		    // update speed info
		    var iSpeed = iDiff.toString() + 'B/s';
		    if (iDiff > 1024 * 1024) {
		        iSpeed = (Math.round(iDiff * 100/(1024*1024))/100).toString() + 'MB/s';
		    } else if (iDiff > 1024) {
		        iSpeed =  (Math.round(iDiff * 100/1024)/100).toString() + 'KB/s';
		    }

		    $('#speed').html(iSpeed);
		    $('#remaining').html('| ' + secondsToTime(secondsRemaining));        
		};
		var uploadProgress = function(e) { // upload process in progress
		    if (e.lengthComputable) {
		        options.iBytesUploaded = e.loaded;
		        options.iBytesTotal = e.total;
		        var iPercentComplete = Math.round(e.loaded * 100 / e.total);
		        var iBytesTransfered = bytesToSize(options.iBytesUploaded);

		        $('#progress_percent').html(iPercentComplete.toString() + '%');
		        $('#progress').css({width:(iPercentComplete * 4).toString() + 'px'});
		        $('#b_transfered').html(iBytesTransfered);
		        if (iPercentComplete == 100) {
		            var oUploadResponse = $(options.uploadResponse);
		            
		            $('#progress_percent').html('99%');
		            oUploadResponse.html('<h1>Please wait...processing</h1>');
		            oUploadResponse.show();
		        }
		    } else {
		        $('#progress').html('unable to compute');
		    }
		};
		var uploadFinish = function(e) { // upload successfully finished
			
		    var oUploadResponse = $(options.uploadResponse);
		    oUploadResponse.html(e.target.responseText);
		    oUploadResponse.show();

		    $('#progress_percent').html('100%');
		    $('#progress').css({width:'400px'});
		    $('#filesize').html(options.sResultFileSize);
		    $('#remaining').html('| 00:00:00');

		    clearInterval(options.oTimer);
		};
		var uploadError = function(e) { // upload error
		    $('#error2').show();
		    clearInterval(options.oTimer);
		};

		var uploadAbort = function(e) { // upload abort
		    $('#abort').show();
		    clearInterval(options.oTimer);
		};
		
		var _this = $(this);
		_this.each(function(i,item){
			var _that = $(item);
			_that.on("change", function(evt){
				//evt.target.files[0];
			    // hide different warnings
			    $(options.uploadResponse).hide();
			    $('#error').hide();
			    $('#error2').hide();
			    $('#abort').hide();
			    $('#warnsize').hide();
			    
			    // get selected file element
			    if(_that[0].files.length == 0)
			    {
			    	alert("please choose a file!");
			    	return;
			    }
			    var oFile = _that[0].files[0];


			    // little test for filesize
			    if (options.iMaxFilesize != -1 && oFile.size > options.iMaxFilesize) {
			        $('#warnsize').show();
			        return;
			    }
			    var progressBar = _that.parent().find(".percent");
			    // prepare HTML5 FileReader
			    var oReader = new FileReader();
			    oReader.onloadstart = function(){
			    	_that.parent().find("#progress_bar").addClass('loading');
			    };
			    oReader.onprogress = function(evt) {
				    // evt is an ProgressEvent.
				    if (evt.lengthComputable) {
				      var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
				      // Increase the progress bar length.
				      if (percentLoaded < 100) {
				    	  progressBar.css({width:percentLoaded+'100%'});
				    	  progressBar.html(percentLoaded + '%');
				      }
				    }
				  };
				
				oReader.onloadend = function() {
					if (oReader.error) {
						console.log(oReader.error);
					}
				};
				var hideProgressBar = function(){
					_that.parent().find("#progress_bar").removeClass('loading');
				};
			    oReader.onload = function(e){
			    	progressBar.css({width:'100%'});
			    	progressBar.html('100%');
			    	setTimeout(hideProgressBar, 2000);
			    };

			    // read selected file as DataURL
			    oReader.readAsDataURL(oFile);
			    
			    // get form data for POSTing
			    //var vFD = $('#upload_form').getFormData(); // for FF3
			    var vFD = new FormData();
			    vFD.append("upload_file", oFile);

			    // create XMLHttpRequest object, adding few event listeners, and POSTing our data
			    var oXHR = new XMLHttpRequest();        
			    oXHR.upload.addEventListener('progress', uploadProgress, false);
			    oXHR.addEventListener('load', uploadFinish, false);
			    oXHR.addEventListener('error', uploadError, false);
			    oXHR.addEventListener('abort', uploadAbort, false);
			    oXHR.open(options.sendMethod, options.url);
			    oXHR.overrideMimeType("application/octet-stream");
			    oXHR.send(vFD);
			    oXHR.onreadystatechange = function() {
					if (oXHR.readyState == 4) {
						if (oXHR.status == 200) {
							console.log("upload complete");
							console.log("response: " + oXHR.responseText);
						}
					}
				};

			    // set inner timer
			    options.oTimer = setInterval(doInnerUpdates, options.timeInterval);
			});
			
		});
	};
})(jQuery);